#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
#include <asm/ptrace.h>

//#define SYMBOL_BEING_PROBED "schedule"
#define SYMBOL_BEING_PROBED "do_sys_open"
//#define SYMBOL_BEING_PROBED "_do_fork"

static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
	int ret;
	const char *pfilename;
	char filename[128] = {0};

	//pr_info("%s---%d\n", __func__, __LINE__);

	//dump_stack();

#ifdef CONFIG_X86

	//pfilename = (const char *)(kernel_stack_pointer(regs) + 8);
	pfilename = (const char *)(regs->si);


	/* you need pay attention to the size of filename, we don't know how applications layer
	 * call open
	 */
	ret = copy_from_user(filename, pfn, 10);
	if (ret != 0) {
		pr_info("copy_from_user failed!ret:%d\n", ret);
		return -1;
	}


	//pr_info("pre_handler--- char: %c, %c\n", *pfn, *(pfn + 1));
	pr_info("pre_handler--- %s\n", filename);
	
	pr_info("<%s> pre_handler: current_task.name:%s, current_task.pid:%d, p->addr = 0x%p, ip = %lx, flags = 0x%lx\n",
		p->symbol_name, current->comm, current->pid, p->addr, regs->ip, regs->flags);

	
#endif

#ifdef CONFIG_MIPS

  pfilename = (const char *)(regs->regs[5]);

	/* you need pay attention to the size of filename, we don't know how applications layer
	 * call open
	 */
	ret = copy_from_user(filename, pfilename, 10);
	if (ret != 0) {
		pr_info("copy_from_user failed!ret:%d\n", ret);
		return -1;
	}


  pr_info("filename:%s\n", filename);
	pr_info("<%s> handler_pre: current_task.name:%s, p->addr = 0x%p, status = 0x%lx\n",
		p->symbol_name, current->comm, p->addr, regs->cp0_status);
#endif

#ifdef CONFIG_LOONGARCH

	//pr_info("<%s> pre_handler: current_task.name:%s, current_task.pid:%d, p->addr = 0x%p, epc = 0x%ls, status = 0x%lx\n", p->symbol_name, current->comm, current->pid, p->addr, regs->csr_epc, regs->csr_estat);
	
#endif



	return 0;
}

static void handler_post(struct kprobe *p, struct pt_regs *regs,
				unsigned long flags)
{
	
	pr_info("%s---%d\n", __func__, __LINE__);
	//dump_stack();

	return ;
}

static struct kprobe kp = {
	.symbol_name = SYMBOL_BEING_PROBED,
};

static int pc_module_init(void)
{
	int ret;
	pr_info("%s---%d\n", __func__, __LINE__);

	kp.pre_handler = handler_pre;
	kp.post_handler = handler_post;


	ret = register_kprobe(&kp);
	if (ret < 0) {
		pr_err("register_kprobe failed, ret:%d\n", ret);
		return ret;
	}


	pr_info("Planted kprobe at %p\n", kp.addr);

	return 0;
}

static void pc_module_exit(void)
{
	pr_info("%s---%d\n", __func__, __LINE__);
	unregister_kprobe(&kp);

	pr_info("kprobe at %p unregistered\n", kp.addr);
	
	return ;
}

module_init(pc_module_init);
module_exit(pc_module_exit);

MODULE_LICENSE("GPL");

